/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#include "pch.h"
#include <journal/app/keys.h>
#include <journal/app/constants.h>

namespace journal { namespace app {

std::shared_ptr<key_registry> key_registry::_singleton;

void key_registry::initialize()
{
    _singleton = std::make_shared<key_registry>();

    _singleton->bind(key::help,                     'h', L"Show this help");
    _singleton->bind(key::debugConsole,             '1', L"Toggle debug console");
    _singleton->bind(key::clearDebugConsole,        'x', L"Clear debug console (DEBUG ONLY)");
    _singleton->bind(key::varConsole,               192, L"Toggle var console");
    _singleton->bind(key::saveThumbnail,            'k', L"Save thumbnail of current page");
    _singleton->bind(key::zoomLevelUp,              189, L"Increase zoom level");
    _singleton->bind(key::zoomLevelDown,            187, L"Decrease zoom level");
    _singleton->bind(key::dumpNotebookModel,        'd', L"Dump notebook model to debug view (DEBUG ONLY)");
    _singleton->bind(key::addNewPage,               'n', L"Create new blank page");
    _singleton->bind(key::cameraModeFocus,          'f', L"Camera mode: change focus");
    _singleton->bind(key::cameraModeRotate,         'r', L"Camera mode: rotate");
    _singleton->bind(key::cameraModeMove,           'm', L"Camera mode: move");
    _singleton->bind(key::cameraModeZoom,           'z', L"Camera mode: zoom");
    _singleton->bind(key::cameraModeRotateLight,    'l', L"Camera mode: rotate light direction");
    _singleton->bind(key::cameraModeOff,            27, L"Camera mode off");
    _singleton->bind(key::restoreCamera,            'y', L"Restore camera");
    _singleton->bind(key::redrawPage,               'c', L"Redraw current page");
    _singleton->bind(key::smoothVectorized,         'v', L"Toggle ink vectorizer on/off");
    _singleton->bind(key::smooth,                   'i', L"Toggle ink smoothing on/off");
    _singleton->bind(key::showDisclaimer,           'w', L"Toggle version info");
    _singleton->bind(key::togglePerf,               'p', L"Toggle performance monitors");
    _singleton->bind(key::testInk1,                 '2', L"Generate test ink");
    _singleton->bind(key::testAnimation1,           '3', L"Toggle test animation 1");
    _singleton->bind(key::testAnimation2,           '4', L"Toggle test animation 2");
    _singleton->bind(key::curlPage,                 '5', L"Curl Page");
    _singleton->bind(key::resetPageCurl,            '6', L"Reset Page Curl");
    _singleton->bind(key::toggleMemoryMonitors,     '7', L"Toggle memory monitors");
    _singleton->bind(key::runTests,                 '8', L"Run Tests");
    _singleton->bind(key::toggleStackExpansion,     '0', L"Expand/collapse paper stack");
    _singleton->bind(key::resetPerformanceMonitors, 'u', L"Reset performance monitors");
    _singleton->bind(key::resetSettings,            'q', L"Reset settings");
    _singleton->bind(key::saveImage,                'g', L"Save page image to file in pictures folder");
    _singleton->bind(key::copy,                     219, L"Copy"); // [
    _singleton->bind(key::paste,                    221, L"Paste"); // ]
    _singleton->bind(key::undo,                     'b', L"Undo");
    _singleton->bind(key::redo,                     'o', L"Redo");
    _singleton->bind(key::credits,                  '9', L"Credits");
}

bool key_registry::checkInternal(const key k, const b::int32 c)
{
    auto it = _bindings.find(k);

    if (it != _bindings.end())
    {
        if (it->second.c == c)
        {
            return true;
        }
        else
        {
            return it->second.c == tolower(c);
        }
    }

    return false;
}

static std::wstring printKey(const b::int32 c)
{
    if (c == 27) 
    {
        return L"ESC";
    }
    else if (c == 187)
    {
        return L"+";
    }
    else if (c == 189)
    {
        return L"-";
    }
    else if (c == 192)
    {
        return L"~";
    }
    else
    {
        b::wchar t[2];
        t[0] = static_cast<b::wchar>(c);
        t[1] = L'\0';
        return std::wstring(t);
    }
}

void key_registry::printHelpInternal()
{
    baja::app::debugConsoleTrace(boost::wformat(L"------------------------------------------------------"), TRACE_TAG_ALWAYS);
    baja::app::debugConsoleTrace(boost::wformat(L"%s help: ") % constants::general::applicationName(), TRACE_TAG_ALWAYS);
    std::for_each(
        _bindings.begin(), 
        _bindings.end(),
        [&](const std::pair<const key, key_binding>& p)
    {
        baja::app::debugConsoleTrace(
            boost::wformat(L"%s: %s") % printKey(p.second.c) % p.second.desc, TRACE_TAG_ALWAYS);
    });
}

}} // namespace journal::app
